"""
utils.py工具类文件：存放驱动对象，隐士等待，最大化窗口
封装
"""
import json

from appium import webdriver
from selenium import webdriver

# 整个项目工程很多地方都需要获取已经创建好的驱动对象
from selenium.webdriver.common.by import By


class UtileDriver:
    # 存储TPshop后台管理系统驱动对象的私有属性（原因：）
    __admin_driver = None

    # 创建或获取驱动对象的公用方法
    # 1、创建驱动对象时需要将创建好的窗口存储到私有属性__admin_driver中也就是要修改该变量值
    # 而只有类级别的方法才有权限修改
    # 2、如果以实例属性的方式存储浏览器对象，name在调用方法时就必须创建utilsdriver的实例对象，
    # 每次创建实例对象，起对应的实例属性都不是同一个，产生的结果还是会打开多个浏览器
    @classmethod
    def get_admin_driver(cls):
        # 如果__admin_driver当前不为空，则代表之前已经打开浏览器，name只需要直接返回已经打开的浏览器驱动对象即可
        if cls.__admin_driver is None:
            # 打开谷歌浏览器
            cls.__admin_driver = webdriver.Chrome()
            # 窗口最大化
            cls.__admin_driver.maximize_window()
            # 隐式等待
            cls.__admin_driver.implicitly_wait(10)
        # 返回创建好的驱动对象
        return cls.__admin_driver

    # 批量运行的时候，只打开一次浏览器
    __admin_key = True

    @classmethod
    def change_admin_key(cls, key):
        cls.__admin_key = key

    # 关闭浏览器驱动对象
    @classmethod
    def quit_admin_driver(cls):
        # 为了代码的健壮性，当浏览器驱动对象为打开的状态下，进行关闭驱动
        if cls.__admin_driver is not None and cls.__admin_key is True:
            # 修改类属性需要用类方法
            cls.__admin_driver.quit()
            # 关闭浏览器后，不能修改后台缓存的驱动对象，所以要将私有属性值改为None为真正的关闭
            cls.__admin_driver = None

    # 定义门户网站为空的驱动对象
    __buyer_driver = None

    # 创建门户网站的类
    @classmethod
    def get_buyer_driver(cls):
        # 如果__admin_driver当前不为空，则代表之前已经打开浏览器，name只需要直接返回已经打开的浏览器驱动对象即可
        if cls.__buyer_driver is None:
            # 打开谷歌浏览器
            cls.__buyer_driver = webdriver.Chrome()
            # 窗口最大化
            cls.__buyer_driver.maximize_window()
            # 隐式等待
            cls.__buyer_driver.implicitly_wait(10)
        # 返回创建好的驱动对象
        return cls.__buyer_driver

    # 关闭门户浏览器驱动对象
    @classmethod
    def quit_buyer_driver(cls):
        # 为了代码的健壮性，当浏览器驱动对象为打开的状态下，进行关闭驱动
        if cls.__buyer_driver is not None:
            # 修改类属性需要用类方法
            cls.__buyer_driver.quit()
            # 关闭浏览器后，不能修改后台缓存的驱动对象，所以要将私有属性值改为None为真正的关闭
            cls.__buyer_driver = None

    # 断言方法
    def is_el_exit(self, drivers, text):
        # 索要定位的元素的xpath定位的文本内容，按照文本定位，看页面中是否存在该文本内容
        xpath_str = "[contains(text(),{}]".format(text)
        # 异常
        try:
            # 驱动对象drivers调用查找元素的位置，文本内容
            is_suc = drivers.find_element(By.XPATH, xpath_str)

        except Exception as e:
            # 找不到元素则返回False
            is_suc = False

        return is_suc

    # APP
    __app_driver = None

    # 创建或获取驱动的对象的公用方法
    # 1、创建驱动对象时需要将创建好的窗口存储到私有属性__admin_driver中也就是要修改该变量值而只有类级别的方法才有权限修改
    # 2、如果以实例属性的方式存储浏览器驱动对象,那么在调用方法时就必须创建UtilsDriver的实例对象,每次创建实例对象,其对应的实例
    # 属性都不是同一个,产生的结果还是会打开多个浏览器
    @classmethod
    def get_app_driver(cls):
        # 如果__admin_driver当前不为空，则代表代码之前已经打开浏览器,那么只需要直接返回已经打开的浏览器驱动对象即可，不需要重新创建
        if cls.__app_driver is None:
            # 手机端启动参数
            desired_caps = dict()
            # 代表被测试的手机系统型号:IOS 和 Android
            desired_caps['platformName'] = 'Android'
            # 代表被测模拟器/手机系统的版本号,可以写部分版本号，但是不能写错
            desired_caps['platformVersion'] = '5.1'
            # 随便写，但是不能不写
            desired_caps['deviceName'] = '323232'
            # 要启动的应用包名
            desired_caps['appPackage'] = 'com.tencent.news'
            # 要启动的界面名
            desired_caps['appActivity'] = '.activity.SplashActivity'
            # 创建驱动对象
            cls.__app_driver = appium.webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
            # 隐式等待
            cls.__app_driver.implicitly_wait(10)
        # 返回创建好的驱动对象
        return cls.__app_driver

    # 关闭BUYER门户网站驱动对象的方法
    @classmethod
    def quit_app_driver(cls):
        # 为加强代码的健壮,防止在没有创建驱动对象之前直接调用关闭驱动对象的方法导致出错的情况则加上判断是否有打开的浏览器
        if cls.__app_driver is not None:
            # 1、直接拿到驱动对象之后调用quit()会关闭浏览器窗口,但是不会清除__admin_driver中的缓存值,如果不清楚,则再次调用get_admin_driver就不会
            # 打开浏览器窗口
            cls.__app_driver.quit()
            # 2、实例方法不能直接修改私有属性所以需要将方法修改为类级别的方法
            cls.__app_driver = None


# 封装读取文件的公用方法
def build_data(filename):
    # 建立一个空列表
    list_str = []
    # 打开文件
    with open(file=filename, encoding="utf-8") as f:
        # 获取json文件中字典的值
        json_data = json.load(f)
        # 遍历值中的values值
        for i in json_data.values():
            list_data = tuple(i.values())
            # 将values值添加到元素中
            list_str.append(list_data)
    # 将元组的数据追加到空列表中
    return list_str
